<template>
    <uv-popup ref="skuPopup" mode="bottom" :closeable="true" :safeAreaInsetBottom="props.safeAreaInsetBottom"
        @change="handleChangePopup">
        <view class="sku-content">
            <view class="godds-box">
                <image class="img" :src="state?.chooseSku?.image"></image>
                <view class="price-box">
                    <view class="price">￥{{ state.chooseSku?.price }}</view>
                    <view class="stock">库存：{{ state.chooseSku?.stock }}</view>
                    <view class="specs">规格：{{ state.chooseSku?.sku_name_arr?.join(',') }}</view>
                </view>
            </view>
            <view class="specs-box">
                <view class="item-box" v-for="item, index in state?.spec_list" :key="index">
                    <view class="title">{{ item.name }}</view>
                    <view class="tag-box">
                        <button v-for="itemChild, indexChild in item?.list" :key="indexChild"
                            :class="['tag',{'active':getSkuSelected(itemChild.name)},{'gray':getSkuDisabled(itemChild.name)}]"
                            @click="handleChooseSku(itemChild.name)" :disabled="getSkuDisabled(itemChild.name)">
                            {{ itemChild.name }}
                            <image v-if="getSkuSelected(itemChild.name)" class="icon-select"
                                :src="handleStaticResources('/static/images/tag-select.png')"> </image>
                        </button>
                    </view>
                </view>
            </view>
            <view class="number-box">
                <view class="tit">数量：</view>
                <uv-number-box v-model="state.numberVal" @change="handleChangeNumberVal"></uv-number-box>
            </view>
            <view class="btn-box">
                <view v-if="props.isShowAddCartBtn" class="core-button-confirm add-cart">
                    <coreshop-button :loading="props.addCartloading" class="core-button-confirm_" :radius="0"
                        title="加入购物车" :customStyle="addCartCustomStyle" @onClick="handleAddCart()"></coreshop-button>
                </view>
                <view class="core-button-confirm">
                    <coreshop-button :loading="props.buyNowNowloading" class="core-button-confirm_" :radius="0"
                        :title="props.btnBuyTitlt" :customStyle="buyNowCustomStyle"
                        @onClick="handleBuyNow()"></coreshop-button>
                </view>
            </view>
        </view>
    </uv-popup>
</template>

<script setup lang="ts">
    import { watch, reactive, ref, computed } from 'vue';
    import type { GoodsSkuListType, GoodsSpecListType } from '@/core/models';
    import { handleStaticResources, handleShowToast } from '@/core/utils';
    import { deepClone } from '@/uni_modules/uv-ui-tools/libs/function/index.js';

    type SpecWeight = Record<string, {
        weight : number;
        sort : number;
    }>

    type SelectedSpec = {
        name : string;
        weight : number;
        sort : number;
    }

    const buyNowCustomStyle = {
        'border': 'none',
        'background-color': '#d33123',
        'flex': 1,
        'padding': '32rpx 0',
        'font-size': '27rpx',
        'text-align': 'center',
        'color': '#fff',
        'height': '90rpx'
    }

    const addCartCustomStyle = {
        ...buyNowCustomStyle,
        'background-color': '#000',
    }


    const props = withDefaults(defineProps<{
        showSku : boolean,
        goodsDetailData : any,
        isShowAddCartBtn : boolean,
        btnBuyTitlt : string,
        safeAreaInsetBottom : boolean;
        buyNowCustomStyle : any,
        buyNowNowloading : boolean,
        addCartloading : boolean
    }>(), {
        showSku: false,
        goodsDetailData: {},
        isShowAddCartBtn: true,
        btnBuyTitlt: '立即购买',
        safeAreaInsetBottom: true,
        buyNowCustomStyle: {
            'border': 'none',
            'background-color': '#d33123',
            'flex': 1,
            'padding': '25rpx 0',
            'font-size': '27rpx',
            'text-align': 'center',
            'color': '#fff',
            'height': '90rpx'
        },
        buyNowNowloading: false,
        addCartloading: false
    });

    const emits = defineEmits(['handleChangePopup', 'handleAddCart', 'handleBuyNow', 'handleChangeGoodSku']);

    const skuPopup = ref();

    const state = reactive<{
        numberVal : number;
        spec_list : Array<GoodsSpecListType>;
        chooseSku : GoodsSkuListType;
        specCombinationList : Array<GoodsSkuListType>;
        specMap : SpecWeight;
        selectedSpecs : Array<SelectedSpec>
    }>({
        numberVal: 1,
        spec_list: [],
        chooseSku: {},
        specCombinationList: [],
        specMap: {},
        selectedSpecs: [],
    });

    watch(() => props.goodsDetailData, (newVal : any) => {
        if (newVal) {
            state.specMap = {};
            state.specCombinationList = [];
            state.selectedSpecs = [];
            // 构造规格权重
            let i = 0, j = 0;
            state.spec_list = deepClone(newVal?.skuList?.spec_list.map((item : GoodsSpecListType) => {
                item.list.forEach((itemChild : GoodsSpecListType) => {
                    state.specMap[itemChild.name] = {
                        sort: i,
                        weight: 1 << j
                    }
                    j++;
                })
                i++;
                return item;
            }));

            state.specCombinationList = (props.goodsDetailData?.skuList?.sku_list.filter((item : GoodsSkuListType) => item.stock > 0)).map((item : GoodsSkuListType) => {
                return {
                    ...item,
                    weight: item.sku_name_arr.reduce((prev, current) => prev + state.specMap[current]?.weight, 0),
                }
            })

            /** 获取数据返回的默认sku,如果有就用没有就找第一个库存不为0的sku */
            let systemDefaultSku : Array<string> = (props.goodsDetailData?.product?.spesDesc?.split(',')).map((item : string) => item.split(':')[1]);
            let skuDefaultSku : GoodsSkuListType = state.specCombinationList.find((item : GoodsSkuListType) => item.sku_name_arr.every((name : string) => systemDefaultSku.includes(name)));
            if (!systemDefaultSku || !skuDefaultSku) {
                state.specCombinationList[0].sku_name_arr.forEach((item : string) => {
                    handleChooseSku(item);
                });
                return;
            }
            skuDefaultSku.sku_name_arr.forEach((item : string) => {
                handleChooseSku(item);
            });
        }
    }, {
        deep: true
    })

    watch(() => props.showSku, (newVal : boolean) => {
        if (newVal) {
            skuPopup.value.open();
        } else {
            skuPopup.value.close();
            state.numberVal = 1;
        }
    })

    const getSkuDisabled = computed(() => {
        return (item : string) => {
            // 每次选中之后要判断其他规格是否能够被选中
            const weights = state.selectedSpecs.reduce((prev, current) => prev + current.weight, 0);
            // 所有是初始状态，则所有属性均可选，因此disabled为false.
            if (weights === 0) return false;
            const current = state.specMap[item];
            const weight = current.weight;
            // 假如选择该属性，这是选中后的“权重之和”
            let sum = weight + weights;
            // 找到是否存在同一维度的规格已被选中的规格
            const existEle = state.selectedSpecs.find(o => o.sort === current.sort);
            if (existEle) {
                // 如果存在，则减去即前选中的规格权重，即替换为当前权重。
                sum -= existEle.weight;
            }
            for (let i = 0; i < state.specCombinationList.length; i++) {
                const sWeight = state.specCombinationList[i].weight!;
                // 与“权重之和”按位与运算后与其进行比较，如果相等，说明该属性是可选的
                if ((sWeight & sum) === sum) {
                    return false;
                }
            }
            return state.selectedSpecs.findIndex(o => o.name === item) == -1;
        };
    })

    const getSkuSelected = computed(() => {
        return (item : string) => {
            return state.selectedSpecs.findIndex(o => o.name === item) > -1;
        };
    })

    /** 商品数量加减变化 */
    const handleChangeNumberVal = (e : any) => {
        state.numberVal = e.value;
    }

    /** sku弹框显示或者隐藏 */
    const handleChangePopup = (e : any) => {
        emits('handleChangePopup', e.show)
    }

    /** sku选择 */
    const handleChooseSku = (name : string) => {
        /** 只有一层的时候，当自己选中时，不能点击自己取消选择 */
        if (state.spec_list.length === 1 && state.selectedSpecs.find((item)=> item.name == name)) {
            return;
        }
        const spec = state.specMap[name];
        const eleIndex = state.selectedSpecs.findIndex(item => item.name === name);
        const sortIndex = state.selectedSpecs.findIndex(item => item.sort === spec.sort);
        // 如果当前元素已经存在，则从列表中删除
        if (eleIndex > -1) {
            state.selectedSpecs.splice(eleIndex, 1);
            return;
        }
        // 如果列表中的元素存在和当前元素的维度相同，则从列表中把那个元素删除，保证同一纬度只有一个元素。
        if (sortIndex > -1) {
            state.selectedSpecs.splice(sortIndex, 1);
        }
        state.selectedSpecs.push({ name: name, weight: spec.weight, sort: spec.sort });
        
        /** 判断sku是否选择完毕 */
        if (state.selectedSpecs.length === state.spec_list.length) {
            let skuName : Array<string> = state.selectedSpecs.map(item => item.name);
            state.chooseSku = state.specCombinationList.find((item : GoodsSkuListType) => item.sku_name_arr.every((name : string) => skuName.includes(name)));
            emits('handleChangeGoodSku', state.chooseSku);
        }
    };

    /** 加入购物车 */
    const handleAddCart = () => {
        if (!handleHaveStock()) {
            return;
        }
        emits('handleAddCart', {
            productId: state.chooseSku._id,
            nums: state.numberVal,
        });

    }

    /** 立即购买 */
    const handleBuyNow = () => {
        if (!handleHaveStock()) {
            return;
        }
        emits('handleBuyNow', {
            productId: state.chooseSku._id,
            nums: state.numberVal,
        });
    }

    /** 判断库存 */
    const handleHaveStock = () => {
        let skuName : Array<string> = state.selectedSpecs.map(item => item.name) || [];
        let sku = state.spec_list.find((item : any) => !item.list.some((itemChild : any) => skuName.includes(itemChild.name)));
        if (sku) {
            handleShowToast(`请选择 ${sku.name} 规格`);
            return false;
        }
        return true;
    }
</script>

<style lang="scss" scoped>
    @import './goods-detail-sku.scss';
</style>